default_platform(:ios)
fastlane_require 'xcodeproj'
fastlane_require 'dotenv'
fastlane_require 'open-uri'

USER_ENV_FILE_PATH = File.join(Dir.home, '.wpios-env.default')
PROJECT_ENV_FILE_PATH = File.expand_path(File.join(Dir.pwd, '../../.configure-files/project.env'))

# Use this instead of getting values from ENV directly
# It will throw an error if the requested value is missing
def get_required_env(key)
  unless ENV.key?(key)
    UI.user_error!("Environment variable '#{key}' is not set. Have you setup #{USER_ENV_FILE_PATH} correctly?")
  end
  ENV[key]
end

before_all do
  # Check that the env files exist
  unless is_ci || File.file?(USER_ENV_FILE_PATH)
    UI.user_error!("~/.wpios-env.default not found: Please copy env/user.env-example to #{USER_ENV_FILE_PATH} and fill in the values")
  end
  unless File.file?(PROJECT_ENV_FILE_PATH)
    UI.user_error!("project.env not found: Make sure your configuration is up to date with `rake dependencies`")
  end

  # This allows code signing to work on CircleCI
  # It is skipped if this isn't running on CI
  # See https://circleci.com/docs/2.0/ios-codesigning/
  setup_circle_ci
end

platform :ios do
########################################################################
# Environment
########################################################################
Dotenv.load(USER_ENV_FILE_PATH)
Dotenv.load(PROJECT_ENV_FILE_PATH)
ENV[GHHELPER_REPO="wordpress-mobile/wordpress-iOS"]
ENV["PROJECT_NAME"]="WordPress"
ENV["PUBLIC_CONFIG_FILE"]="../config/Version.Public.xcconfig"
ENV["INTERNAL_CONFIG_FILE"]="../config/Version.internal.xcconfig"
ENV["DOWNLOAD_METADATA"]="./fastlane/download_metadata.swift"
ENV["PROJECT_ROOT_FOLDER"]="../"

########################################################################
# Screenshots 
########################################################################
import "./ScreenshotFastfile"

########################################################################
# Release Lanes
########################################################################
  #####################################################################################
  # code_freeze
  # -----------------------------------------------------------------------------------
  # This lane executes the steps planned on code freeze
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane code_freeze [skip_confirm:<skip confirm>]
  #
  # Example:
  # bundle exec fastlane code_freeze
  # bundle exec fastlane code_freeze skip_confirm:true
  #####################################################################################
  desc "Creates a new release branch from the current develop"
  lane :code_freeze do | options |
    old_version = ios_codefreeze_prechecks(options)
    
    ios_bump_version_release()
    new_version = ios_get_app_version()
    ios_update_release_notes(new_version: new_version)
    setbranchprotection(repository:GHHELPER_REPO, branch: "release/#{new_version}")
    setfrozentag(repository:GHHELPER_REPO, milestone: new_version)

    ios_localize_project()
    ios_tag_build()
    get_prs_list(repository:GHHELPER_REPO, start_tag:"#{old_version}", report_path:"#{File.expand_path('~')}/wpios_prs_list_#{old_version}_#{new_version}.txt")
  end

  #####################################################################################
  # update_appstore_strings
  # -----------------------------------------------------------------------------------
  # This lane updates the AppStoreStrings.po files with the latest content from
  # the release_notes.txt file and the other text sources
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane update_appstore_strings version:<release note version>
  #
  # Example:
  # bundle exec fastlane update_appstore_strings version:10.7
  #####################################################################################
  desc "Updates the AppStoreStrings.po file with the latest data"
  lane :update_appstore_strings do | options |
    prj_folder = Pathname.new(File.join(Dir.pwd, "../..")).expand_path.to_s
    source_metadata_folder = File.join(prj_folder, "Scripts/fastlane/appstoreres/metadata/source")

    files = {
      whats_new: File.join(prj_folder,  "/WordPress/Resources/release_notes.txt"),
      app_store_subtitle: File.join(source_metadata_folder, "subtitle.txt"),
      app_store_desc: File.join(source_metadata_folder, "description.txt"),
      app_store_keywords: File.join(source_metadata_folder, "keywords.txt"),
      "standard-whats-new-1" => File.join(source_metadata_folder, "standard_whats_new_1.txt"),
      "standard-whats-new-2" => File.join(source_metadata_folder, "standard_whats_new_2.txt"),
      "standard-whats-new-3" => File.join(source_metadata_folder, "standard_whats_new_3.txt"),
      "standard-whats-new-4" => File.join(source_metadata_folder, "standard_whats_new_4.txt"),
      "app_store_screenshot-1" => File.join(source_metadata_folder, "promo_screenshot_1.txt"),
      "app_store_screenshot-2" => File.join(source_metadata_folder, "promo_screenshot_2.txt"),
      "app_store_screenshot-3" => File.join(source_metadata_folder, "promo_screenshot_3.txt"),
      "app_store_screenshot-4" => File.join(source_metadata_folder, "promo_screenshot_4.txt"),
      "app_store_screenshot-5" => File.join(source_metadata_folder, "promo_screenshot_5.txt"),
    }

    ios_update_metadata_source(po_file_path: prj_folder + "/WordPress/Resources/AppStoreStrings.po", 
      source_files: files, 
      release_version: options[:version])
  end

  #####################################################################################
  # new_beta_release
  # -----------------------------------------------------------------------------------
  # This lane updates the release branch for a new beta release. It will update the
  # current release branch by default. If you want to update a different branch
  # (i.e. hotfix branch) pass the related version with the 'base_version' param
  # (example: base_version:10.6.1 will work on the 10.6.1 branch)
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane new_beta_release [skip_confirm:<skip confirm>] [base_version:<version>]
  #
  # Example:
  # bundle exec fastlane new_beta_release
  # bundle exec fastlane new_beta_release skip_confirm:true
  # bundle exec fastlane new_beta_release base_version:10.6.1
  #####################################################################################
  desc "Updates a release branch for a new beta release"
  lane :new_beta_release do | options |
    ios_betabuild_prechecks(options)
    ios_bump_version_beta()
    ios_tag_build()
  end

  #####################################################################################
  # new_hotfix_release
  # -----------------------------------------------------------------------------------
  # This lane updates the release branch for a new hotix release. 
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane new_hotfix_release [skip_confirm:<skip confirm>] [version:<version>]
  #
  # Example:
  # bundle exec fastlane new_hotfix_release version:10.6.1
  # bundle exec fastlane new_hotfix_release skip_confirm:true version:10.6.1
  #####################################################################################
  desc "Creates a new hotfix branch from the given tag"
  lane :new_hotfix_release do | options |
    prev_ver = ios_hotfix_prechecks(options)
    ios_bump_version_hotfix(previous_version: prev_ver, version: options[:version])
    ios_tag_build()
  end

  #####################################################################################
  # finalize_release
  # -----------------------------------------------------------------------------------
  # This lane finalize a release: updates store metadata, pushes the final tag and  
  # cleans all the temp ones
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane finalize_release [skip_confirm:<skip confirm>] [version:<version>] 
  #
  # Example:
  # bundle exec fastlane finalize_release 
  # bundle exec fastlane finalize_release skip_confirm:true 
  #####################################################################################
  desc "Removes all the temp tags and puts the final one"
  lane :finalize_release do | options |
    ios_finalize_prechecks(options)
    ios_update_metadata(options) unless ios_current_branch_is_hotfix
    ios_bump_version_beta() unless ios_current_branch_is_hotfix
    ios_final_tag(options)

    # Wrap up
    version = ios_get_app_version()
    removebranchprotection(repository:GHHELPER_REPO, branch: "release/#{version}")
    setfrozentag(repository:GHHELPER_REPO, milestone: version, freeze: false)
    create_new_milestone(repository:GHHELPER_REPO)
    close_milestone(repository:GHHELPER_REPO, milestone: version)
  end

  #####################################################################################
  # build_and_upload_release
  # -----------------------------------------------------------------------------------
  # This lane builds the app and upload it for both internal and external distribution 
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane build_and_upload_release [skip_confirm:<skip confirm>]
  #
  # Example:
  # bundle exec fastlane build_and_upload_release 
  # bundle exec fastlane build_and_upload_release skip_confirm:true 
  #####################################################################################
  desc "Builds and updates for distribution"
  lane :build_and_upload_release do | options |
    ios_build_prechecks(skip_confirm: options[:skip_confirm], 
      internal: true,
      external: true)
    ios_build_preflight()
    build_and_upload_internal(skip_prechecks: true, skip_confirm: options[:skip_confirm])
    build_and_upload_itc(skip_prechecks: true, skip_confirm: options[:skip_confirm])
  end

  #####################################################################################
  # build_and_upload_installable_build
  # -----------------------------------------------------------------------------------
  # This lane builds the app and upload it for adhoc testing 
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane build_and_upload_installable_build [version_long:<version_long>]
  #
  # Example:
  # bundle exec fastlane build_and_upload_installable_build 
  # bundle exec fastlane build_and_upload_installable_build build_number:123 
  #####################################################################################
  desc "Builds and uploads an installable build"
  lane :build_and_upload_installable_build do | options |
    alpha_code_signing

    # Get the current build version, and update it if needed
    version_config_path = "../../config/Version.internal.xcconfig"
    versions = Xcodeproj::Config.new(File.new(version_config_path)).to_hash
    build_number = versions["VERSION_LONG"]

    if options.key?(:build_number)
      build_number = options[:build_number]

      UI.message("Updating build version to #{build_number}")

      versions["VERSION_LONG"] = build_number
      new_config = Xcodeproj::Config.new(versions)
      new_config.save_as(Pathname.new(version_config_path))
    end

    gym(
      scheme: "WordPress Alpha",
      workspace: "../WordPress.xcworkspace",
      export_method: "enterprise",
      clean: true,
      output_directory: "../build/",
      derived_data_path: "../derived-data/alpha/",
      export_team_id: ENV["INT_EXPORT_TEAM_ID"],
      export_options: { method: "enterprise" })

    sh("mv ../../build/WordPress.ipa \"../../build/WordPress Alpha.ipa\"")
      
    appcenter_upload(
      api_token: get_required_env("APPCENTER_API_TOKEN"),
      owner_name: "automattic",
      owner_type: "organization", 
      app_name: "WPiOS-One-Offs",
      file: "../build/WordPress Alpha.ipa",
      destinations: "All-users-of-WPiOS-One-Offs",
      notify_testers: false 
    )

    download_url = Actions.lane_context[SharedValues::APPCENTER_DOWNLOAD_LINK]
    UI.message("Successfully built and uploaded installable build here: #{download_url}")
    install_url = "https://install.appcenter.ms/orgs/automattic/apps/WPiOS-One-Offs/"

    # Create a comment.json file so that Peril to comment with the build details, if this is running on CI
    comment_body = "You can test the changes on this Pull Request by downloading it from AppCenter [here](#{install_url}) with build number: #{build_number}. IPA is available [here](#{download_url}). If you need access to this, you can ask a maintainer to add you."
    File.write("comment.json", { body: comment_body }.to_json)
  end

  #####################################################################################
  # build_and_upload_internal
  # -----------------------------------------------------------------------------------
  # This lane builds the app and upload it for internal testing  
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane build_and_upload_internal [skip_confirm:<skip confirm>]
  #
  # Example:
  # bundle exec fastlane build_and_upload_internal 
  # bundle exec fastlane build_and_upload_internal skip_confirm:true 
  #####################################################################################
  desc "Builds and uploads for distribution"
  lane :build_and_upload_internal do | options |
    ios_build_prechecks(skip_confirm: options[:skip_confirm], internal: true) unless (options[:skip_prechecks])
    ios_build_preflight() unless (options[:skip_prechecks])

    internal_code_signing

    gym(
      scheme: "WordPress Internal",
      workspace: "../WordPress.xcworkspace",
      export_method: "enterprise",
      clean: true,
      output_directory: "../build/",
      derived_data_path: "../derived-data/internal/",
      export_team_id: get_required_env("INT_EXPORT_TEAM_ID"),
      export_options: { method: "enterprise" })

    sh("mv ../../build/WordPress.ipa \"../../build/WordPress Internal.ipa\"")

    appcenter_upload(
      api_token: ENV["APPCENTER_API_TOKEN"],
      owner_name: "automattic",
      owner_type: "organization", 
      app_name: "WP-Internal",
      file: "../build/WordPress Internal.ipa",
      notify_testers: false 
    )
    

    dSYM_PATH = File.dirname(File.dirname(Dir.pwd)) + "/build/WordPress.app.dSYM.zip"

    sentry_upload_dsym(
      auth_token: get_required_env("SENTRY_AUTH_TOKEN"),
      org_slug: 'a8c',
      project_slug: 'wordpress-ios',
      dsym_path: dSYM_PATH,
    )
   
  end

  #####################################################################################
  # build_and_upload_itc
  # -----------------------------------------------------------------------------------
  # This lane builds the app and upload it for external distribution  
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane build_and_upload_itc [skip_confirm:<skip confirm>] [create_release:<Create release on GH> ]
  #
  # Example:
  # bundle exec fastlane build_and_upload_itc 
  # bundle exec fastlane build_and_upload_itc skip_confirm:true 
  # bundle exec fastlane build_and_upload_itc create_release:true 
  #####################################################################################
  desc "Builds and uploads for distribution"
  lane :build_and_upload_itc do | options |
    ios_build_prechecks(skip_confirm: options[:skip_confirm], external: true) unless (options[:skip_prechecks])
    ios_build_preflight() unless (options[:skip_prechecks])

    appstore_code_signing

    gym(scheme: "WordPress", workspace: "../WordPress.xcworkspace",
      clean: true,
      export_team_id: get_required_env("EXT_EXPORT_TEAM_ID"), 
      derived_data_path: "../derived-data/itc/",
      export_options: { method: "app-store" }
    )

    testflight(
      skip_waiting_for_build_processing: true,
      team_id: "299112",
    )

    sh("cd .. && rm WordPress.ipa")
    dSYM_PATH = File.dirname(Dir.pwd) + "/WordPress.app.dSYM.zip"

    sentry_upload_dsym(
      dsym_path: dSYM_PATH,
      auth_token: get_required_env("SENTRY_AUTH_TOKEN"),
      org_slug: 'a8c',
      project_slug: 'wordpress-ios',
    )

    sh("cd .. && rm WordPress.app.dSYM.zip")

    if (options[:create_release])
      archive_zip_path = File.dirname(Dir.pwd) + "/WordPress.xarchive.zip"
      zip(path: lane_context[SharedValues::XCODEBUILD_ARCHIVE], output_path: archive_zip_path)

      version = ios_get_app_version()
      create_release(repository:GHHELPER_REPO, 
        version: version, 
        release_notes_file_path:'../WordPress/Resources/release_notes.txt',
        release_assets:"#{archive_zip_path}"
      )

      sh("rm #{archive_zip_path}") 
    end
  end

  #####################################################################################
  # build_release
  # -----------------------------------------------------------------------------------
  # This lane builds the app, create a GH release and upload it for external distribution  
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane build_release [skip_confirm:<skip confirm>]
  #
  # Example:
  # bundle exec fastlane build_release 
  # bundle exec fastlane build_release skip_confirm:true 
  #####################################################################################
  desc "Builds, create release and uploads for distribution"
  lane :build_release do | options |
    build_and_upload_itc(skip_confirm: options[:skip_confirm], create_release: true)
  end

########################################################################
# Cnfigure Lanes
########################################################################
  #####################################################################################
  # update_certs_and_profiles
  # -----------------------------------------------------------------------------------
  # This lane downloads all the required certs and profiles and, 
  # if not run on CI it creates the missing ones.
  # -----------------------------------------------------------------------------------
  # Usage:
  # bundle exec fastlane update_certs_and_profiles 
  #
  # Example:
  # bundle exec fastlane update_certs_and_profiles 
  #####################################################################################
  lane :update_certs_and_profiles do | options |
    alpha_code_signing
    internal_code_signing
    appstore_code_signing
  end

  ########################################################################
  # Fastlane match code signing
  ########################################################################  
  private_lane :alpha_code_signing do |options|
    match(
      type: "enterprise",
      team_id: get_required_env("INT_EXPORT_TEAM_ID"),
      readonly: options[:readonly] || is_ci,
      app_identifier: ["org.wordpress.alpha",
                       "org.wordpress.alpha.WordPressShare",
                       "org.wordpress.alpha.WordPressDraftAction",
                       "org.wordpress.alpha.WordPressTodayWidget",
                       "org.wordpress.alpha.WordPressNotificationServiceExtension",
                       "org.wordpress.alpha.WordPressNotificationContentExtension", 
                       "org.wordpress.alpha.WordPressAllTimeWidget",
                       "org.wordpress.alpha.WordPressThisWeekWidget"])
  end

  private_lane :internal_code_signing do |options|
    match(
      type: "enterprise",
      team_id: get_required_env("INT_EXPORT_TEAM_ID"),
      readonly: options[:readonly] || is_ci,
      app_identifier: ["org.wordpress.internal",
                       "org.wordpress.internal.WordPressShare",
                       "org.wordpress.internal.WordPressDraftAction",
                       "org.wordpress.internal.WordPressTodayWidget",
                       "org.wordpress.internal.WordPressNotificationServiceExtension",
                       "org.wordpress.internal.WordPressNotificationContentExtension",
                       "org.wordpress.internal.WordPressAllTimeWidget",
                       "org.wordpress.internal.WordPressThisWeekWidget"])
  end

  private_lane :appstore_code_signing do |options|
    match(
      type: "appstore",
      team_id: get_required_env("EXT_EXPORT_TEAM_ID"),
      readonly: options[:readonly] || is_ci,
      app_identifier: ["org.wordpress",
                       "org.wordpress.WordPressShare",
                       "org.wordpress.WordPressDraftAction",
                       "org.wordpress.WordPressTodayWidget",
                       "org.wordpress.WordPressNotificationServiceExtension",
                       "org.wordpress.WordPressNotificationContentExtension",
                       "org.wordpress.WordPressAllTimeWidget",
                       "org.wordpress.WordPressThisWeekWidget"])
  end

########################################################################
# Helper Lanes
########################################################################  
  desc "Get a list of pull request from `start_tag` to the current state"
  lane :get_pullrequests_list do | options |
    get_prs_list(repository:GHHELPER_REPO, start_tag:"#{options[:start_tag]}", report_path:"#{File.expand_path('~')}/wpios_prs_list.txt")
  end

end
